<?php
/**
 * Created by PhpStorm.
 * User: pc
 * Date: 2024/1/27
 * Time: 15:12
 */

namespace app\common\controllers;

use app\common\enum\ConfigEnum;
use app\common\service\OptionMap;
use sookie\react\AdminController;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;

class AdminOptionsController extends AdminController
{

    protected $class_obj;
    public function afterAction($action, $result)
    {
        $id = $action->id;
        if(method_exists($this,$id)){
            $result = $this->$id($result);
        }
        return parent::afterAction($action, $result); // TODO: Change the autogenerated stub
    }

    /**
     * @return bool|OptionMap
     */
    protected function getClassInstance(){
        $controller_id = \Yii::$app->controller->id;
        $class_name = $this->getClassName($controller_id);
        $class = 'app\\common\\service\\options\\'.$class_name;
        if(class_exists($class)){
            if(empty($this->class_obj)){
                $this->class_obj = $class::getInstance();
            }
            return $this->class_obj;
        }
        return false;
    }
    protected function setSearchConfigOptions($result , $key = 'searchConfig'){
        $obj = $this->getClassInstance();
        $config = ArrayHelper::getValue($result,$key);
        if(($obj instanceof OptionMap) && $config){
            if(method_exists($this,'findModel') && empty($obj->getModel()) && ($id = \Yii::$app->request->get("id"))){
                $model = $this->findModel($id);
                $obj->setModel($model);
            }
            $result[$key] = $obj->setSearchConfigOptions($config);
        }
        return $result;
    }

    protected function replaceOptions($result , $key = 'data' , $is_list = false){
        $obj = $this->getClassInstance();
        $config = ArrayHelper::getValue($result,$key);
        if($is_list){
            if($config){
                foreach ($config as $index => $config_item){
                    if(($obj instanceof OptionMap) && $config_item){
                        $result[$key][$index] = $obj->replaceOptions($config_item);
                    }
                }
            }

        }else{
            if(($obj instanceof OptionMap) && $config){
                $result[$key] = $obj->replaceOptions($config);
            }
        }

        return $result;
    }

    protected function index($result){
        $result = $this->indexConfigCallback($result);//callback要先执行，否则原值会被替换掉
        $result = $this->setSearchConfigOptions($result);
        $result = $this->replaceOptions($result,'data',true);//替换原值
        return $result;
    }

    protected function update($result){
        $key = 'config';
        $result = $this->setSearchConfigOptions($result,$key);
        return $result;
    }

    protected function sr($result){
        $key = 'config';
        $result = $this->setSearchConfigOptions($result,$key);
        return $result;
    }

    protected function create($result){
        $key = 'config';
        $result = $this->setSearchConfigOptions($result,$key);
        return $result;
    }

    protected function view($result){
        $result = $this->configCallback($result);//callback要先执行，否则原值会被替换掉
        $result = $this->replaceOptions($result);//替换原值
        return $result;
    }

    //处理index页面的回调函数
    protected function indexConfigCallback($result,$data_key = 'data',$config_key = 'tableConfig',$is_list = true){
        $data = ArrayHelper::getValue($result,$data_key);
        $config = ArrayHelper::getValue($result,$config_key.".columns");
        if($config){
            $config_index = ArrayHelper::index($config,ConfigEnum::KEY);
            foreach ($config_index as $field => $config_item){
                if($is_list){
                    foreach ($data as $index => $data_item){
                        if($data_item instanceof ActiveRecord ){
                            $data_item = $data_item->toArray();
                            $data[$index] = $data_item;
                        }
                        if($config_item && isset($config_item[ConfigEnum::CALLBACK]) && is_callable($config_item[ConfigEnum::CALLBACK])){
                            $data[$index][$field] = $this->handelConfigCallback($config_item[ConfigEnum::CALLBACK],$data_item,$field,ArrayHelper::getValue($data_item,$field));
                        }

                    }
                }else{
                    if($data instanceof ActiveRecord ){
                        $data = $data->toArray();
                    }
                    if($config_item && isset($config_item[ConfigEnum::CALLBACK]) && is_callable($config_item[ConfigEnum::CALLBACK])){
                        $data[$field] = $this->handelConfigCallback($config_item[ConfigEnum::CALLBACK],$data,$field,ArrayHelper::getValue($data,$field));
                    }

                }
            }
            $result[$data_key] = $data;
        }

        $config_action = ArrayHelper::getValue($result,$config_key.".actions");
        if($config_action){
            foreach ($config_action as $config_item){
                if($is_list){
                    foreach ($data as $index => $data_item){
                        if($data_item instanceof ActiveRecord ){
                            $data_item = $data_item->toArray();
                            $data[$index] = $data_item;
                        }
                        if($config_item && isset($config_item[ConfigEnum::CALLBACK]) && is_callable($config_item[ConfigEnum::CALLBACK])){
                            $data[$index]['display'][]  = $this->handelActionsCallback($config_item[ConfigEnum::CALLBACK],$data_item,$config_item);
                        }

                    }
                }else{
                    if($data instanceof ActiveRecord ){
                        $data = $data->toArray();
                    }
                    if($config_item && isset($config_item[ConfigEnum::CALLBACK]) && is_callable($config_item[ConfigEnum::CALLBACK])){
                        $display = $this->handelActionsCallback($config_item[ConfigEnum::CALLBACK],$data,$config_item);
                        $data['display'][] = $display;
                    }

                }
                $result[$data_key] = $data;
            }
        }
        return $result;
    }

    //处理view页面的回调函数
    protected function configCallback($result,$data_key = 'data',$config_key = 'config',$is_list = false){
        $data = ArrayHelper::getValue($result,$data_key);
        $config = ArrayHelper::getValue($result,$config_key);
        $config_index = ArrayHelper::index($config,ConfigEnum::FIELD);
        foreach ($config_index as $field => $config_item){
            if($is_list){
                foreach ($data as $index => $data_item){
                    if($data_item instanceof ActiveRecord ){
                        $data_item = $data_item->toArray();
                        $data[$index] = $data_item;
                    }
                    if($config_item && isset($config_item[ConfigEnum::CALLBACK]) && is_callable($config_item[ConfigEnum::CALLBACK])){
                        $data[$index][$field] = $this->handelConfigCallback($config_item[ConfigEnum::CALLBACK],$data_item,$field,ArrayHelper::getValue($data_item,$field));
                    }

                }
            }else{
                if($data instanceof ActiveRecord ){
                    $data = $data->toArray();
                }
                if($config_item && isset($config_item[ConfigEnum::CALLBACK]) && is_callable($config_item[ConfigEnum::CALLBACK])){
                    $data[$field] = $this->handelConfigCallback($config_item[ConfigEnum::CALLBACK],$data,$field,ArrayHelper::getValue($data,$field));
                }

            }
        }
        $result[$data_key] = $data;
        return $result;
    }

    protected function handelConfigCallback($callback , $field_item = [] ,$field = '', $value = ''){
        $value = $callback($field_item,$field,$value);
        return $value;
    }

    protected function handelActionsCallback($callback , $field_item = [],$config = []){
        $value = $callback($field_item,$config);
        return $value;
    }

    protected function getClassName($controller_id){
        $arr_name = explode("/",$controller_id);
        $arr_new = array_map(function($name,$k){
            return $k == 0 ? $name : ucfirst($name);
        },$arr_name,array_keys($arr_name));
        return implode("",$arr_new);
    }
}